using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data.Common;
using System.Data;
using System.Globalization;
using System.ComponentModel;

namespace ResourceBlender_Express {
    /// <summary>
    /// A window for managing elements and resources used by an application
    /// </summary>
    public partial class WinResourcesGrid : Window {
        private Database db;
        private ObservableSortedDictionary<string, string> bundles,
                                                           languages;
        private SortedDictionary<int, string> resourceCache;
        private string resourceSql, // the 'xxx - snippet...' selection query for generating the resource cache
                       crossTabColumns, // the field selection part of the cross-tab query. Saves writing the same huge switch on both forms.
                       crossTabSql; // the whole crosstab query
        private RBApplication application;

        private DataTemplate ascSorted,
                             descSorted;

        /// <summary>
        /// Initializes a new <see cref="WinResourcesGrid"/>.
        /// </summary>
        /// <param name="app">The application to edit.</param>
        /// <param name="bundles">The bundles to show.</param>
        /// <param name="languages">The languages to show.</param>
        public WinResourcesGrid(RBApplication app, ObservableSortedDictionary<string, string> bundles, ObservableSortedDictionary<string, string> languages) {
            InitializeComponent();
            ascSorted = (DataTemplate)FindResource("HeaderTemplateAsc");
            descSorted = (DataTemplate)FindResource("HeaderTemplateDesc");
            this.bundles = bundles;
            this.languages = languages;
            this.application = app;
            this.Closing += (s, e) => {
                ResourceBlender_Express.Properties.Settings.Default.Save();
            };

            string[] filterItems = new string[] {
                "Contains",
                "Starts With",
                "Ends With"
            };
            string[] translationFilterItems = new string[4];
            Array.Copy(filterItems, translationFilterItems,3);
            translationFilterItems[3] = "Is Blank";

            cboBundleFilter.ItemsSource = filterItems;
            cboElementFilter.ItemsSource = filterItems;
            cboElementCommentFilter.ItemsSource = filterItems;
            cboResourceCommentFilter.ItemsSource = filterItems;
            cboTranslationFilter.ItemsSource = translationFilterItems;
            cboTranslationFilterLanguage.ItemsSource = languages;

            cboBundleFilter.SelectedIndex = 0;
            cboElementFilter.SelectedIndex = 0;
            cboElementCommentFilter.SelectedIndex = 0;
            cboResourceCommentFilter.SelectedIndex = 0;
            cboTranslationFilter.SelectedIndex = 0;
            cboTranslationFilterLanguage.SelectedValue = app.DefaultLanguage;

            resourceCache = new SortedDictionary<int, string>();
            StringBuilder sqlBuffer = new StringBuilder();
            string bundleFormat = null,
 //                  crossTabFormat = null,
                   crossTabEnd = null;
            if(db == null) {
                db = new Database();
            }
            switch(db.InstanceType) {
                case Database.DatabaseType.MySQL:
                case Database.DatabaseType.SQLServer:
                    bundleFormat = "'{0}', ";
                    break;
                case Database.DatabaseType.SQLite:
                    bundleFormat = "\"{0}\", ";
                    break;
            }
            foreach(KeyValuePair<string, string> bundle in bundles) {
                sqlBuffer.AppendFormat(bundleFormat, bundle.Key);
            }
            sqlBuffer.Remove(sqlBuffer.Length - 2, 1); // remove last comma
            string bundleSql = sqlBuffer.ToString();
            sqlBuffer.Remove(0, sqlBuffer.Length);

            switch(db.InstanceType) {
                case Database.DatabaseType.MySQL:
                    resourceSql = @"SELECT DISTINCT resourceid, 
                                        CAST(IF(CHAR_LENGTH(translation) < 20, 
                                            CONCAT(resourceid, ' - ',translation), 
                                            CONCAT(resourceid, ' - ',SUBSTRING(translation,1,17),'...')
                                         ) AS CHAR) AS display
                                        FROM " + db.TablePrefix + "resources WHERE language = @defaultLang ORDER BY resourceid ASC";
                    crossTabEnd = string.Format(@" FROM {0}elements AS e
                            INNER JOIN {0}resources AS r ON r.resourceid = e.resourceid 
                            LEFT JOIN {0}bundles AS b ON b.id = e.bundle
                            LEFT JOIN {0}resourcecomments AS c ON r.resourceid = c.resourceid 
                            WHERE applicationid = @pID AND bundle IN ({1}) 
                            GROUP BY e.id 
                            ORDER BY bundle, elementname ", db.TablePrefix, bundleSql);
                    break;
                case Database.DatabaseType.SQLServer:
                    resourceSql = @"SELECT DISTINCT resourceid, display = CAST(resourceid AS VARCHAR)+' - '+
                                        CASE
                                         WHEN LEN(translation) < 20 THEN translation
                                         ELSE SUBSTRING(translation,1,17)+'...'
                                        END
                                        FROM " + db.TablePrefix + "resources WHERE language = @defaultLang ORDER BY resourceid ASC";
                    crossTabEnd = string.Format(@" FROM {0}elements AS e
                            INNER JOIN {0}resources AS r ON r.resourceid = e.resourceid
                            LEFT JOIN {0}bundles AS b ON b.id = e.bundle
                            LEFT JOIN {0}resourcecomments AS c ON r.resourceid = c.resourceid
                            WHERE applicationid = @pID  AND bundle IN ({1}) 
                            GROUP BY e.id,e.resourceid,applicationid,bundle,elementname,e.comment,c.comment,b.name
                            ORDER BY bundle, elementname", db.TablePrefix, bundleSql);
                    break;
                case Database.DatabaseType.SQLite:
                    resourceSql = @"SELECT DISTINCT resourceid, (CAST(resourceid AS VARCHAR) || ' - '||
                                    CASE
                                     WHEN LENGTH(translation) < 20 THEN translation
                                     ELSE SUBSTR(translation,1,17)||'...'
                                    END) AS display 
                                    FROM " + db.TablePrefix + "resources WHERE language = @defaultLang ORDER BY resourceid ASC";
                    crossTabEnd = string.Format(@" FROM {0}elements AS e
                            INNER JOIN {0}resources AS r ON r.resourceid = e.resourceid
                            LEFT JOIN {0}bundles AS b ON b.id = e.bundle
                            LEFT JOIN {0}resourcecomments AS c ON r.resourceid = c.resourceid
                            WHERE applicationid = @pID  AND bundle IN ({1}) 
                            GROUP BY e.id,e.resourceid,applicationid,bundle,elementname,e.comment,c.comment,b.name
                            ORDER BY bundle, elementname", db.TablePrefix, bundleSql);
                    break;
            }
            GridViewColumn col;
            string defaultLanguageName = null;
            try {
                defaultLanguageName = CultureInfo.GetCultureInfo(application.DefaultLanguage).EnglishName;
            } catch {
                defaultLanguageName = application.DefaultLanguage;
            }
            col = new GridViewColumn();
            col.Header = defaultLanguageName;
            col.DisplayMemberBinding = new Binding(application.DefaultLanguage);
            col.Width = 120;
            grdResources.Columns.Add(col);

            foreach(KeyValuePair<string, string> language in languages) {
                if(language.Key == application.DefaultLanguage)
                    continue;
                col = new GridViewColumn();
                col.Header = language.Value;
                col.DisplayMemberBinding = new Binding(language.Key);
                col.Width = 120;
                grdResources.Columns.Add(col);
            }
            crossTabColumns = db.GetCrosstabLanguageSql(languages);
            sqlBuffer.Append(crossTabColumns);

            sqlBuffer.Insert(0, @"SELECT e.id, applicationid, bundle, elementname, e.resourceid, e.comment AS elementcomment, c.comment as resourcecomment, b.name AS bundlename,");
            sqlBuffer.AppendFormat(crossTabEnd);
            crossTabSql = sqlBuffer.ToString();

            RefreshResources();
        }

        /// <summary>
        /// Opens the help file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void ShowHelp(object sender, ExecutedRoutedEventArgs e) {
            Utils.OpenHelp("Translating.an.Application.html");
        }

        /// <summary>
        /// Opens the 'Unused Resources' window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void ShowUnused(object sender, ExecutedRoutedEventArgs e) {
            WinUnusedResources dlg = new WinUnusedResources(languages);
            dlg.Owner = this;
            dlg.ShowDialog();
            RefreshResources();
        }

        /// <summary>
        /// Opens the 'Duplicate Resources' window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void ShowDuplicates(object sender, ExecutedRoutedEventArgs e) {
            WinDuplicateResources dlg = new WinDuplicateResources(languages);
            dlg.Owner = this;
            dlg.ShowDialog();
            RefreshResources();
        }

        /// <summary>
        /// Refreshes the grid of resources.
        /// </summary>
        private void RefreshResources() {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                try {
                    if(db == null || !db.Connected) {
                        db = new Database();
                        db.OpenConnection();
                    }
                    using(Database.Command cmd = db.CreateCommand()) {
                        cmd.CommandText = crossTabSql;
                        cmd.AddParameterWithValue("@pID", application.ID);
                        Database.DataAdapter adapter = new Database.DataAdapter(cmd);
                        DataTable dtResults = new DataTable();
                        adapter.Fill(dtResults);
                        dwe.Result = dtResults;
                    }
                } catch(Exception ex) {
                    dwe.Result = ex.Message;
                } finally {
                    if(db != null) {
                        try {
                            db.CloseConnection();
                        } catch { }
                    }
                }
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                if(rwe.Result is DataTable) {
                    lstGrid.DataContext = rwe.Result;
                    ResourceBlenderCommands.FilterGrid.Execute(null, null);
                    lstGrid.IsEnabled = true;
                    RefreshResourceCache();
                } else {
                    DialogBox.ShowAlert(this, "Error: Could not connect to database - " + rwe.Result.ToString(), "Database Error");
                }
            };
            SetStatus("Loading resources...", true);
            lstGrid.IsEnabled = false;
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Refreshes the cache of resources.
        /// </summary>
        private void RefreshResourceCache() {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                try {
                    if(db == null || !db.Connected) {
                        db = new Database();
                        db.OpenConnection();
                    }
                    using(Database.Command cmd = db.CreateCommand()) {
                        SortedDictionary<int, string> cache = new SortedDictionary<int, string>();
                        cmd.CommandText = resourceSql;
                        cmd.AddParameterWithValue("@defaultLang", application.DefaultLanguage);
                        DbDataReader reader = cmd.ExecuteReader();
                        cache.Add(-1, "New Resource");
                        while(reader.Read()) {
                            cache.Add(int.Parse(reader["resourceid"].ToString()), reader["display"].ToString());
                        }
                        reader.Close();
                        dwe.Result = cache;
                    }
                } catch(Exception ex) {
                    dwe.Result = ex.Message;
                } finally {
                    if(db != null) {
                        try {
                            db.CloseConnection();
                        } catch { }
                    }
                }
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                if(rwe.Result is string) {
                    DialogBox.ShowAlert(this, "Error: Could not connect to database - " + rwe.Result.ToString(), "Database Error");
                } else {
                    resourceCache = rwe.Result as SortedDictionary<int, string>;
                }
            };
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Shows a window to add a new element.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void AddElement(object sender, ExecutedRoutedEventArgs e) {
            RBElement element = new RBElement();
            element.Application = application;
            element.BundleID = bundles.First().Key;
            element.BundleName = bundles.First().Value;
            RBResource res = new RBResource();
            foreach(KeyValuePair<string, string> language in languages) {
                res.Translations.Add(language.Key, new RBTranslation(language.Key, string.Empty, string.Empty));
            }
            element.Resource = res;
            WinAddElement dlg = new WinAddElement(bundles, resourceCache, crossTabColumns, languages, element, application.DefaultLanguage);
            dlg.ResourcesChanged += () => { RefreshResources(); };
            dlg.Show();
        }

        /// <summary>
        /// Determines whether the edit element command can be executed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteEditElement(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = lstGrid != null && lstGrid.SelectedItem != null;
            e.Handled = true;
        }

        /// <summary>
        /// Shows a window to edit an element.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void EditElement(object sender, ExecutedRoutedEventArgs e) {
            if(lstGrid.SelectedItem == null) {
                return;
            }
            DataRow row = (lstGrid.SelectedItem as DataRowView).Row;
            DataColumnCollection cols = row.Table.Columns; // this is tightly linked with the crosstab query above!
            object[] elementData = row.ItemArray;
            RBElement selectedElement = new RBElement(int.Parse(elementData[0].ToString()), elementData[3].ToString(), elementData[2].ToString(), elementData[7].ToString(), elementData[5].ToString());
            selectedElement.Application = application;
            // This element does not include the translators comments as retrieving them requires another query.
            // This is only executed if the user decides to edit the resource used for the element
            RBResource res = new RBResource(int.Parse(elementData[4].ToString()), elementData[6].ToString());
            for(int i = 8; i < elementData.Length; i++) {
                string languageCode = cols[i].ColumnName; 
                res.Translations.Add(languageCode, new RBTranslation(languageCode, elementData[i].ToString(), string.Empty));
            }
            selectedElement.Resource = res;
            WinAddElement dlg = new WinAddElement(bundles, resourceCache, crossTabColumns, languages, selectedElement, application.DefaultLanguage);
            dlg.ResourcesChanged += () => { RefreshResources(); };
            dlg.Show();
        }

        /// <summary>
        /// Determines whether the delete element command can be executed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteDeleteElement(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = lstGrid != null && lstGrid.SelectedItem != null;
            e.Handled = true;
        }

        /// <summary>
        /// Shows a prompt to confirm deletion of an element, then deletes it from the database.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void DeleteElement(object sender, ExecutedRoutedEventArgs e) {
            if(lstGrid.SelectedItem == null) {
                return;
            }
            object[] elementData = (lstGrid.SelectedItem as DataRowView).Row.ItemArray; // this is tightly linked with the crosstab query above!
            string elementName = elementData[3].ToString(),
                   elementId = elementData[0].ToString();
            if(DialogBox.Show(this, string.Format("The element '{0}' wil be deleted. Any resources or translations will be left intact.{1}{1}Are you sure?", elementName, Environment.NewLine), "Confirm Delete", DialogBox.DialogBoxType.YesNo, DialogBox.DialogBoxIcon.Warning, DialogBox.DialogBoxButton.No) == DialogBox.DialogBoxButton.Yes) {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += (s, dwe) => {
                    try {
                        if(db == null || !db.Connected) {
                            db = new Database();
                            db.OpenConnection();
                        }
                        using(Database.Command cmd = db.CreateCommand()) {
                            cmd.CommandText = "DELETE FROM " + db.TablePrefix + "elements WHERE applicationid = @pID AND id = @eID";
                            cmd.AddParameterWithValue("@pID", application.ID);
                            cmd.AddParameterWithValue("@eID", elementId);
                            cmd.ExecuteNonQuery();
                        }
                    } catch(Exception ex) {
                        dwe.Result = ex.Message;
                    } finally {
                        if(db != null) {
                            try {
                                db.CloseConnection();
                            } catch { }
                        }
                    }
                };
                worker.RunWorkerCompleted += (s, rwe) => {
                    SetStatus(null, false);
                    if(rwe.Result == null) {
                        RefreshResources();
                    } else {
                        DialogBox.ShowAlert(this, "Error: Could not connect to database - " + rwe.Result.ToString(), "Database Error");
                    }
                };
                SetStatus("Loading...", true);
                worker.RunWorkerAsync();
            }
        }

        /// <summary>
        /// Executes the ResourceBlenderCommands.Properties command 
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void lstGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
            ResourceBlenderCommands.Edit.Execute(null, this);
        }

        #region Sorting and Filtering
        /// <summary>
        /// Applies filters to the grid.
        /// </summary>
        private void FilterGrid(object sender, ExecutedRoutedEventArgs e) {
            StringBuilder filterBuffer = new StringBuilder();
            if(e.Parameter == null || (e.Parameter as string) != "clear") {
                string bundle = txtBundleFilter.Text,
                       element = txtElementFilter.Text,
                       elementComment = txtElementCommentFilter.Text,
                       resourceComment = txtResourceCommentFilter.Text,
                       translation = txtTranslationFilter.Text;
                if(!string.IsNullOrEmpty(bundle)) {
                    filterBuffer.Append("bundlename like ");
                    switch(cboBundleFilter.SelectedIndex) {
                        case 0:
                            filterBuffer.Append("'%").Append(bundle).Append("%'");
                            break;
                        case 1:
                            filterBuffer.Append("'").Append(bundle).Append("%'");
                            break;
                        case 2:
                            filterBuffer.Append("'%").Append(bundle).Append("'");
                            break;
                    }
                }
                if(!string.IsNullOrEmpty(element)) {
                    if(filterBuffer.Length > 0) {
                        filterBuffer.Append(" and ");
                    }
                    filterBuffer.Append("elementname like ");
                    switch(cboElementFilter.SelectedIndex) {
                        case 0:
                            filterBuffer.Append("'%").Append(element).Append("%'");
                            break;
                        case 1:
                            filterBuffer.Append("'").Append(element).Append("%'");
                            break;
                        case 2:
                            filterBuffer.Append("'%").Append(element).Append("'");
                            break;
                    }
                }
                if(!string.IsNullOrEmpty(elementComment)) {
                    if(filterBuffer.Length > 0) {
                        filterBuffer.Append(" and ");
                    }
                    filterBuffer.Append("elementcomment like ");
                    switch(cboElementCommentFilter.SelectedIndex) {
                        case 0:
                            filterBuffer.Append("'%").Append(elementComment).Append("%'");
                            break;
                        case 1:
                            filterBuffer.Append("'").Append(elementComment).Append("%'");
                            break;
                        case 2:
                            filterBuffer.Append("'%").Append(elementComment).Append("'");
                            break;
                    }
                }
                if(!string.IsNullOrEmpty(resourceComment)) {
                    if(filterBuffer.Length > 0) {
                        filterBuffer.Append(" and ");
                    }
                    filterBuffer.Append("resourcecomment like ");
                    switch(cboResourceCommentFilter.SelectedIndex) {
                        case 0:
                            filterBuffer.Append("'%").Append(resourceComment).Append("%'");
                            break;
                        case 1:
                            filterBuffer.Append("'").Append(resourceComment).Append("%'");
                            break;
                        case 2:
                            filterBuffer.Append("'%").Append(resourceComment).Append("'");
                            break;
                    }
                }
                if(cboTranslationFilter.SelectedIndex == 3) {
                    if(filterBuffer.Length > 0) {
                        filterBuffer.Append(" and ");
                    }
                    filterBuffer.Append('[').Append(cboTranslationFilterLanguage.SelectedValue).Append("] IS NULL");
                } else if(!string.IsNullOrEmpty(translation)) {
                    if(filterBuffer.Length > 0) {
                        filterBuffer.Append(" and ");
                    }
                    filterBuffer.Append('[').Append(cboTranslationFilterLanguage.SelectedValue).Append("] like ");
                    switch(cboTranslationFilter.SelectedIndex) {
                        case 0:
                            filterBuffer.Append("'%").Append(translation).Append("%'");
                            break;
                        case 1:
                            filterBuffer.Append("'").Append(translation).Append("%'");
                            break;
                        case 2:
                            filterBuffer.Append("'%").Append(translation).Append("'");
                            break;
                    }
                }
            } else {
                txtBundleFilter.Text = string.Empty;
                txtElementFilter.Text = string.Empty;
                txtElementCommentFilter.Text = string.Empty;
                txtResourceCommentFilter.Text = string.Empty;
                txtTranslationFilter.Text = string.Empty;
            }
            DataTable tbl = (lstGrid.DataContext as DataTable);
            tbl.DefaultView.RowFilter = filterBuffer.ToString();
            lstGrid.DataContext = tbl;
            int numRows = tbl.Rows.Count;
            int numExcluded = numRows - tbl.DefaultView.Count;
            SetStatus(string.Format("{0} {1}{2}", numRows, numRows == 1 ? "element" : "elements", numExcluded > 0 ? string.Format(" ({0} excluded by filters)", numExcluded) : ""), false);
        }

        /// <summary>
        /// Fires the FilterGrid command if 'Live Filters' is checked
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void cboFilter_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            if(chkLiveFilter.IsChecked != true) {
                return;
            }
            ResourceBlenderCommands.FilterGrid.Execute(null, null);
        }

        /// <summary>
        /// Fires the FilterGrid command if 'Live Filters' is checked
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
        private void txtFilter_TextChanged(object sender, TextChangedEventArgs e) {
            if(chkLiveFilter.IsChecked != true) {
                return;
            }
            ResourceBlenderCommands.FilterGrid.Execute(null, null);
        }

        /// <summary>
        /// Sorts the grid.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnColumnHeaderClick(object sender, RoutedEventArgs e) {
            if(e.OriginalSource is GridViewColumnHeader) { // sort the grid
                GridViewColumn column = ((GridViewColumnHeader)e.OriginalSource).Column;
                string sortPath = column.DisplayMemberBinding == null ? (column.CellTemplate.DataType ?? string.Empty).ToString() : (column.DisplayMemberBinding as Binding).Path.Path;
                if(sortPath.Length == 0) {
                    return; // no field specified
                }
                if(column.HeaderTemplate == ascSorted) {
                    column.HeaderTemplate = null;
                    (lstGrid.DataContext as DataTable).DefaultView.Sort = sortPath + " DESC"; ;
                } else if(column.HeaderTemplate == descSorted) {
                    column.HeaderTemplate = ascSorted;
                    (lstGrid.DataContext as DataTable).DefaultView.Sort = "";
                } else {
                    column.HeaderTemplate = ascSorted;
                    (lstGrid.DataContext as DataTable).DefaultView.Sort = sortPath + " ASC";
                }
            }
        }
        #endregion

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void CloseWindow(object sender, ExecutedRoutedEventArgs e) {
            Close();
        }

        /// <summary>
        /// Sets the text on the status message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="showProgress"><c>true</c> if the progress bar should be shown, otherwise <c>false</c>.</param>
        private void SetStatus(string message, bool showProgress) {
            prgStatus.Visibility = showProgress ? Visibility.Visible : Visibility.Hidden;
            if(message == null) {
                lblStatus.Visibility = Visibility.Hidden;
            } else {            
                lblStatus.Visibility = Visibility.Visible;
                lblStatus.Content = message;
            }
        }
    }
}
